#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import aiohttp
import json
import logging
from dotenv import load_dotenv
import time

# 获取logger
logger = logging.getLogger("deepseek语音助手")

class DeepSeekClient:
    """使用DeepSeek V3 API的客户端封装"""
    
    def __init__(self):
        """初始化DeepSeek V3客户端"""
        load_dotenv()
        
        # 获取API密钥
        api_key = os.getenv("DEEPSEEK_API_KEY")
        if not api_key:
            # 尝试处理可能的Unicode BOM问题
            for key in os.environ.keys():
                if "DEEPSEEK_API_KEY" in key:
                    api_key = os.environ[key]
                    logger.info(f"找到API密钥: {key[:5]}...")
                    break
        
        if not api_key:
            logger.error("DEEPSEEK_API_KEY环境变量未设置")
            raise ValueError("DEEPSEEK_API_KEY环境变量未设置")
            
        self.api_key = api_key
        
        # 获取API基础URL，默认使用官方文档中的URL
        self.api_base = os.getenv("DEEPSEEK_API_BASE", "https://api.deepseek.com")
        
        # 确保api_base不以/结尾
        if self.api_base.endswith("/"):
            self.api_base = self.api_base[:-1]
        
        # 模型名称，默认为deepseek-chat (DeepSeek-V3)
        self.model = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")
        
        logger.info(f"DeepSeek配置: API Base: {self.api_base}, 模型: {self.model}")
        logger.info("DeepSeek客户端初始化成功")
        
        # 系统提示词 - 用于引导模型以适当的方式回答
        self.system_prompt = (
            "你是deepseek语音助手，一个友好、专业的人工智能助手。"
            "请提供简洁、准确、有用的回答。"
            "回答应该是自然的口语化表达，适合语音播报。"
            "避免使用长句和复杂术语，尽量使用简单词汇。"
            "不要列出项目符号或格式化文本，所有回答应该是连贯的语音流。"
            "你的回答应该简明扼要，避免冗长的开场白或结束语。"
            "如果无法回答某个问题，请直接说明无法提供该信息，不要提供不准确的答案。"
        )
    
    async def get_response(self, query):
        """获取单次查询的回复"""
        return await self._call_api([
            {"role": "system", "content": self.system_prompt},
            {"role": "user", "content": query}
        ])
    
    async def get_response_with_history(self, conversation_history):
        """使用对话历史获取回复"""
        # 创建完整的对话历史，包括系统提示
        messages = [{"role": "system", "content": self.system_prompt}]
        # 如果已提供了system角色，则不再添加
        if len(conversation_history) > 0 and conversation_history[0].get("role") == "system":
            messages = conversation_history
        else:
            messages.extend(conversation_history)
        
        return await self._call_api(messages)
    
    async def _call_api(self, messages):
        """调用DeepSeek V3 API并返回生成的回复文本"""
        
        # 构建API请求数据
        payload = {
            "model": self.model,     # 使用配置的模型名称
            "messages": messages,
            "temperature": 0.7,      # 控制创造性，0.7是平衡值
            "max_tokens": 1000,      # 最大生成令牌数
            "top_p": 0.95,           # 控制多样性
            "stream": False          # 不使用流式响应
        }
        
        # 详细记录API请求信息
        logger.info(f"请求DeepSeek API，模型: {self.model}, 消息数: {len(messages)}")
        logger.debug(f"请求消息结构: {[m.get('role', 'unknown') for m in messages]}")
        logger.debug(f"API请求内容: {json.dumps(payload, ensure_ascii=False)[:200]}...")
        
        try:
            # 构建正确的API端点，根据文档标准格式
            # DeepSeek API使用与OpenAI兼容的格式: {base_url}/v1/chat/completions
            api_endpoint = f"{self.api_base}/v1/chat/completions"
            logger.info(f"API端点: {api_endpoint}")
            
            # 记录完整的请求参数
            logger.debug(f"请求头: Authorization: Bearer {self.api_key[:5]}..., Content-Type: application/json")
            logger.debug(f"请求体: {json.dumps(payload, ensure_ascii=False)}")
            
            # 发送API请求
            start_time = time.time()
            async with aiohttp.ClientSession() as session:
                headers = {
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                }
                
                async with session.post(
                    api_endpoint,
                    headers=headers,
                    json=payload,  # 使用json参数自动处理序列化和Content-Type
                    timeout=30     # 设置30秒超时
                ) as response:
                    end_time = time.time()
                    response_time = round((end_time - start_time) * 1000)
                    logger.info(f"API响应状态码: {response.status}, 响应时间: {response_time}ms")
                    
                    response_text = await response.text()
                    logger.debug(f"原始响应: {response_text[:500]}...")
                    
                    if response.status != 200:
                        logger.error(f"DeepSeek API返回错误: {response.status}, {response_text[:500]}")
                        # 尝试解析错误详情
                        try:
                            error_data = json.loads(response_text)
                            if 'error' in error_data:
                                error_detail = error_data['error']
                                logger.error(f"错误详情: {error_detail}")
                        except:
                            pass
                        return "抱歉，我遇到了技术问题，无法回答你的问题。请稍后再试。"
                    
                    try:
                        result = json.loads(response_text)
                    except json.JSONDecodeError:
                        logger.error(f"解析API响应失败: {response_text[:200]}")
                        return "抱歉，我收到了无效的响应格式。请稍后再试。"
                    
                    if not result.get("choices") or not result["choices"]:
                        logger.error(f"DeepSeek API返回无效结果: {result}")
                        return "抱歉，我无法生成有效的回复。"
                    
                    # 提取生成的回复文本
                    content = result["choices"][0]["message"]["content"]
                    
                    # 记录token用量信息
                    if "usage" in result:
                        usage = result["usage"]
                        logger.info(f"Token用量: 输入={usage.get('prompt_tokens', '未知')}, "
                                   f"输出={usage.get('completion_tokens', '未知')}, "
                                   f"总计={usage.get('total_tokens', '未知')}")
                    
                    # 简单清理，确保适合语音输出
                    content = content.replace("\n", " ").strip()
                    
                    logger.info(f"收到DeepSeek回复: {content[:100]}...")
                    return content
                    
        except aiohttp.ClientError as e:
            logger.error(f"API请求客户端错误: {e}")
            return "抱歉，无法连接到DeepSeek服务器。请检查网络连接或稍后再试。"
        except asyncio.TimeoutError:
            logger.error("API请求超时")
            return "抱歉，请求超时，无法获取回复。请稍后再试。"
        except Exception as e:
            logger.error(f"调用DeepSeek API时出错: {type(e).__name__}: {e}")
            import traceback
            logger.error(f"详细错误: {traceback.format_exc()}")
            return "抱歉，我暂时无法连接到服务器。请稍后再试。"

# 简单测试函数
async def test_deepseek_client():
    """测试DeepSeek客户端功能"""
    try:
        client = DeepSeekClient()
        logger.info("测试单轮对话...")
        response = await client.get_response("今天天气怎么样？")
        logger.info(f"单轮对话回复: {response}")
        
        logger.info("测试多轮对话...")
        conversation = [
            {"role": "user", "content": "你好，请介绍一下自己"},
            {"role": "assistant", "content": "你好！我是DeepSeek语音助手，一个基于DeepSeek V3模型的AI助手。有什么我可以帮助你的吗？"},
            {"role": "user", "content": "今天是几号？"}
        ]
        response2 = await client.get_response_with_history(conversation)
        logger.info(f"多轮对话回复: {response2}")
        
        return response
    except Exception as e:
        logger.error(f"测试DeepSeek客户端时出错: {e}")
        import traceback
        logger.error(f"详细错误: {traceback.format_exc()}")
        return None

if __name__ == "__main__":
    # 配置日志
    logging.basicConfig(
        level=logging.DEBUG,  # 测试时使用DEBUG级别
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    
    import asyncio
    
    # 测试
    asyncio.run(test_deepseek_client()) 